package com.sakura.demo.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: zhengcan
 * @Date: 2022/5/11
 * @Description: FastJson工具类
 * @Version: 1.0.0 创建
 */
@Slf4j
public class FastJsonUtil {

    public FastJsonUtil() {
    }

    public static boolean valid(String json) {
        return JSON.isValid(json);
    }

    public static <V> List<V> fromJsonArray(String json, Class<V> c) {
        return JSONObject.parseArray(json, c);
    }

    public static <V> V from(Object jsonObj, Class<V> c) {
        return JSON.parseObject(jsonObj.toString(), c);
    }

    public static <V> V from(String json, Class<V> c) {
        return JSON.parseObject(json, c);
    }

    public static <V> V from(String json, TypeReference<V> typeReference) {
        return JSON.parseObject(json, typeReference.getType(), new Feature[0]);
    }

    public static <V> String to(List<V> list) {
        return Objects.isNull(list) ? "[]" : JSON.toJSONString(list);
    }

    public static <V> String to(V v) {
        return Objects.isNull(v) ? "{}" : JSON.toJSONString(v);
    }

    public static <V> String toFormatJson(V v) {
        return format(to(v));
    }

    public static <V> String toFormatJson(List<V> list) {
        return format(to(list));
    }

    public static String getString(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return null;
            } else {
                try {
                    return jsonObject.getString(key);
                } catch (Exception e) {
                    log.error("fastjson get string error, json:{}, key:{}", json, key);
                    return null;
                }
            }
        }
    }

    public static Integer getInt(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return null;
            } else {
                try {
                    return jsonObject.getInteger(key);
                } catch (Exception e) {
                    log.error("fastjson get Int error, json:{}, key:{}", json, key);
                    return null;
                }
            }
        }
    }

    public static Long getLong(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return null;
            } else {
                try {
                    return jsonObject.getLong(key);
                } catch (Exception e) {
                    log.error("fastjson get Long error, json:{}, key:{}", json, key);
                    return null;
                }
            }
        }
    }

    public static Double getDouble(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return null;
            } else {
                try {
                    return jsonObject.getDouble(key);
                } catch (Exception e) {
                    log.error("fastjson get Double error, json:{}, key:{}", json, key);
                    return null;
                }
            }
        }
    }

    public static BigInteger getBigInteger(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return new BigInteger(String.valueOf(0.0D));
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return new BigInteger(String.valueOf(0.0D));
            } else {
                try {
                    return jsonObject.getBigInteger(key);
                } catch (Exception e) {
                    log.error("fastjson get BigInteger error, json:{}, key:{}", json, key);
                    return null;
                }
            }
        }
    }

    public static BigDecimal getBigDecimal(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return null;
            } else {
                try {
                    return jsonObject.getBigDecimal(key);
                } catch (Exception e) {
                    log.error("fastjson get BigDecimal error, json:{}, key:{}", json, key);
                    return null;
                }
            }
        }
    }

    public static boolean getBoolean(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return false;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject == null) {
                return false;
            } else {
                try {
                    return jsonObject.getBooleanValue(key);
                } catch (Exception e) {
                    log.error("fastjson get Boolean error, json:{}, key:{}", json, key);
                    return false;
                }
            }
        }
    }

    public static Byte getByte(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            return jsonObject == null ? null : jsonObject.getByteValue(key);
        }
    }

    public static <T> List<T> getList(String json, String key, Class<T> c) {
        if (StringUtils.isEmpty(json)) {
            return null;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(json);
            List<T> ts = null;
            if (jsonObject != null) {
                try {
                    JSONArray jsonArray = jsonObject.getJSONArray(key);
                    ts = jsonArray.toJavaList(c);
                } catch (Exception e) {
                    log.error("fastjson get List error, json:{}, key:{}", json, key);
                }
            }

            return ts;
        }
    }

    public static Map<String, Object> getMap(String json) {
        return (Map)(StringUtils.isBlank(json) ? new HashMap(16) : JSONObject.parseObject(json));
    }

    public static <T> String add(String json, String key, T value) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        add(jsonObject, key, value);
        return jsonObject.toString();
    }

    private static <T> void add(JSONObject jsonObject, String key, T value) {
        if (!(value instanceof String) && !(value instanceof Number) && !(value instanceof Boolean) && !(value instanceof Byte[])) {
            jsonObject.put(key, to(value));
        } else {
            jsonObject.put(key, value);
        }

    }

    public static String remove(String json, String key) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        jsonObject.remove(key);
        return jsonObject.toString();
    }

    public static <T> String update(String json, String key, T value) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        add(jsonObject, key, value);
        return jsonObject.toString();
    }

    public static String format(String json) {
        try {
            JSONObject jsonObject = JSONObject.parseObject(json);
            return JSON.toJSONString(jsonObject, new SerializerFeature[]{SerializerFeature.PrettyFormat});
        } catch (Exception e) {
            log.warn("格式化失败,即将转为json集合format");
            return formatArray(json);
        }
    }

    public static String formatArray(String json) {
        JSONArray jsonArray = JSONObject.parseArray(json);
        return JSON.toJSONString(jsonArray, new SerializerFeature[]{SerializerFeature.PrettyFormat});
    }

    public static boolean isJson(String json) {
        return JSON.isValid(json);
    }
}
